#nullable enable
using Godot;
using AndroidUnevenRoadGame.Game;

namespace AndroidUnevenRoadGame.UI
{
    public partial class MapScene : Control
    {
        [Export] private Label? _floorLabel;
        [Export] private Label? _goldLabel;
        [Export] private VBoxContainer? _mapContainer;

        public override void _Ready()
        {
            _floorLabel ??= GetNode<Label>("MainLayout/InfoPanel/FloorLabel");
            _goldLabel ??= GetNode<Label>("MainLayout/InfoPanel/GoldLabel");
            _mapContainer ??= GetNode<VBoxContainer>("MainLayout/MapScroll/MapContainer");

            var game = GameRoot.Instance;
            game.StateChanged += OnGameStateChanged;
            game.GoldChanged += OnGoldChanged;
            game.FloorChanged += OnFloorChanged;

            UpdateFloor(game.CurrentFloor);
            UpdateGold(game.PlayerGold);
            RenderMap();
        }

        public override void _ExitTree()
        {
            if (!Engine.IsEditorHint() && GameRoot.Instance != null)
            {
                var game = GameRoot.Instance;
                game.StateChanged -= OnGameStateChanged;
                game.GoldChanged -= OnGoldChanged;
                game.FloorChanged -= OnFloorChanged;
            }
        }

        private void OnGameStateChanged(int stateValue)
        {
            var state = (GameRoot.GameState)stateValue;
            Visible = state == GameRoot.GameState.Map;
            if (Visible)
            {
                RenderMap();
            }
        }

        private void OnGoldChanged(int gold) => UpdateGold(gold);

        private void OnFloorChanged(int floor)
        {
            UpdateFloor(floor);
            RenderMap();
        }

        private void UpdateGold(int gold)
        {
            if (_goldLabel != null)
            {
                _goldLabel.Text = $"金币：{gold}";
            }
        }

        private void UpdateFloor(int floor)
        {
            if (_floorLabel != null)
            {
                _floorLabel.Text = $"当前楼层：{floor}";
            }
        }

        private void RenderMap()
        {
            if (_mapContainer == null)
            {
                return;
            }

            foreach (Node child in _mapContainer.GetChildren())
            {
                child.QueueFree();
            }

            var game = GameRoot.Instance;
            var floors = game.MapSystem.Floors;

            foreach (var floor in floors)
            {
                var floorRow = new HBoxContainer();
                floorRow.AddThemeConstantOverride("separation", 12);
                floorRow.SizeFlagsHorizontal = Control.SizeFlags.ExpandFill;

                var title = new Label
                {
                    Text = GetFloorTitle(floor.Index, game),
                    CustomMinimumSize = new Vector2(120, 0),
                    SizeFlagsVertical = Control.SizeFlags.ShrinkCenter
                };
                title.AddThemeColorOverride("font_color", GetFloorTitleColor(floor.Index, game));
                floorRow.AddChild(title);

                for (var nodeIndex = 0; nodeIndex < floor.Nodes.Count; nodeIndex++)
                {
                    var node = floor.Nodes[nodeIndex];
                    var button = new Button
                    {
                        Text = GetNodeLabel(node.Type),
                        SizeFlagsHorizontal = Control.SizeFlags.ExpandFill,
                        SizeFlagsVertical = Control.SizeFlags.ShrinkCenter,
                        FocusMode = Control.FocusModeEnum.All
                    };

                    var fontColor = Colors.LightGray;

                    if (floor.Index < game.CurrentFloor)
                    {
                        button.Disabled = true;
                        fontColor = Colors.SlateGray;
                        if (game.TryGetSelectedMapNode(floor.Index, out var selected) && selected == nodeIndex)
                        {
                            button.Text = $"✔ {GetNodeLabel(node.Type)}\n(已通关)";
                            fontColor = Colors.Goldenrod;
                        }
                        else
                        {
                            button.Text += "\n(未选择)";
                        }
                    }
                    else if (floor.Index == game.CurrentFloor)
                    {
                        var reachable = IsNodeReachable(floor.Index, nodeIndex);
                        if (game.TryGetSelectedMapNode(floor.Index, out var selectedIndex) && selectedIndex == nodeIndex)
                        {
                            button.Text = $"★ {GetNodeLabel(node.Type)}\n(当前选择)";
                            fontColor = Colors.Gold;
                        }
                        else if (reachable)
                        {
                            button.Disabled = false;
                            fontColor = Colors.LightGreen;
                        }
                        else
                        {
                            button.Text += "\n(未连通)";
                            fontColor = Colors.DimGray;
                            button.Disabled = false;
                        }

                        button.Pressed += () => OnMapNodePressed(floor.Index, nodeIndex, node);
                    }
                    else
                    {
                        button.Disabled = true;
                        fontColor = Colors.DarkSlateGray;
                    }

                    button.AddThemeColorOverride("font_color", fontColor);
                    button.AddThemeColorOverride("font_color_pressed", fontColor);
                    button.AddThemeColorOverride("font_color_hover", fontColor);

                    floorRow.AddChild(button);
                }

                _mapContainer.AddChild(floorRow);
            }
        }

        private bool IsNodeReachable(int floorIndex, int nodeIndex)
        {
            if (floorIndex <= 1)
            {
                return true;
            }

            var game = GameRoot.Instance;
            if (!game.TryGetSelectedMapNode(floorIndex - 1, out var previousNode))
            {
                return floorIndex == game.CurrentFloor;
            }

            var previousFloor = game.MapSystem.Floors[floorIndex - 2];
            if (previousNode < 0 || previousNode >= previousFloor.Nodes.Count)
            {
                return false;
            }

            return previousFloor.Nodes[previousNode].Connections.Contains(nodeIndex);
        }

        private static string GetFloorTitle(int floorIndex, GameRoot game)
        {
            if (floorIndex < game.CurrentFloor)
            {
                return $"第 {floorIndex} 层（已通关）";
            }

            if (floorIndex == game.CurrentFloor)
            {
                return $"第 {floorIndex} 层（当前）";
            }

            return $"第 {floorIndex} 层（未探索）";
        }

        private static Color GetFloorTitleColor(int floorIndex, GameRoot game)
        {
            if (floorIndex < game.CurrentFloor)
            {
                return Colors.SlateGray;
            }

            if (floorIndex == game.CurrentFloor)
            {
                return Colors.Gold;
            }

            return Colors.LightGray;
        }

        private void OnMapNodePressed(int floorIndex, int nodeIndex, MapNode node)
        {
            var game = GameRoot.Instance;
            game.SetCurrentMapNode(floorIndex, nodeIndex);

            switch (node.Type)
            {
                case MapNodeType.Battle:
                    StartRandomEncounter("battle", MapNodeType.Battle);
                    break;
                case MapNodeType.Elite:
                    StartRandomEncounter("elite", MapNodeType.Elite);
                    break;
                case MapNodeType.Boss:
                    StartRandomEncounter("boss", MapNodeType.Boss);
                    break;
                case MapNodeType.Event:
                    game.EventManager.GenerateRandomEvent();
                    game.ChangeState(GameRoot.GameState.Event);
                    break;
                case MapNodeType.Shop:
                    game.GenerateShopOffers();
                    game.ChangeState(GameRoot.GameState.Shop);
                    break;
                case MapNodeType.Hanfu:
                    game.ChangeState(GameRoot.GameState.Hanfu);
                    break;
            }

            RenderMap();
        }

        private void StartEncounter(string encounterId, MapNodeType nodeType)
        {
            var enemies = EnemyDatabase.GetEncounter(encounterId);
            if (enemies.Count == 0)
            {
                GD.PushWarning($"未配置遭遇战：{encounterId}");
                return;
            }

            GameRoot.Instance.BattleManager.StartBattle(enemies, nodeType);
        }

        private void StartRandomEncounter(string category, MapNodeType nodeType)
        {
            var rng = GameRoot.Instance.Random;
            var encounterId = EnemyDatabase.GetRandomEncounterId(category, rng) ?? category;
            StartEncounter(encounterId, nodeType);
        }

        private static string GetNodeLabel(MapNodeType type)
        {
            return type switch
            {
                MapNodeType.Battle => "战斗",
                MapNodeType.Elite => "精英战",
                MapNodeType.Boss => "首领战",
                MapNodeType.Event => "奇遇事件",
                MapNodeType.Shop => "补给商店",
                MapNodeType.Hanfu => "汉府休整",
                _ => type.ToString()
            };
        }
    }
}

